package com.ruoyi.core.lock;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

/**
 * Redis Distributed lock
 */
public class Lock {

    private static final Logger logger = LoggerFactory.getLogger(Lock.class);

    private RedissonClient redissonClient;

    private boolean locked = false;

    private RLock lock;

    //Automatically unlock
    private Long unlock_max_time;

    //Max await fetch lock time.
    private Long await_time;

    public Lock(Long unlock_max_time, Long await_time) {
        this.unlock_max_time = unlock_max_time;
        this.await_time = await_time;
    }

    public Lock() {
        this.unlock_max_time = 20L;
        this.await_time = 20L;
    }

    public void lock(String name) {

        redissonClient = RedissonUtil.getRedissonClient();

        lock = redissonClient.getLock(name);
        try {
            locked = lock.tryLock(await_time, unlock_max_time, TimeUnit.SECONDS);
            if (locked) {
                logger.info("Fetch Lock [{}] Use ThreadProcess [{}]", name, Thread.currentThread().getName());
            }else{
                logger.info("Lock [{}] Using. Request ThreadProcess [{}]",name, Thread.currentThread().getName());
                throw new InterruptedException();
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    public void unLock() {
        if (locked) {
            if (lock.getHoldCount() > 0) {
                String name = lock.getName();
                logger.info("UnLock[{}] Thread[{}]", name, Thread.currentThread().getName());
                lock.unlock();
            } else {
                logger.warn("UnLock Thread [{}],The current thread no longer holds the lock", Thread.currentThread().getName());
            }
        }
    }

    public static void main(String[] args) {
        Lock lock2 = new Lock();
        lock2.lock("1");
        lock2.unLock();
    }

}
